/***********************************************************************
 * 描述:		此文件中包含多个类和枚举
 *			ApiResultFlag:接口调用结果状态枚举
 *			ApiResult:后端接口返回到业务的数据结果结构
 *			ApiSort:排序信息类
 *			ApiQueryCriteria:查询条件实体结构
 *			ApiPage:分页实体结构：分页查询及结果返回格式，包含参数信息、排序信息和结果信息。
 *			ApiClient:该类是一个通用的供客户端上层调用后端接口的工具类，主要是用来通过接口访问数据库及其他服务器资源操作。
 * File:    apiclient.h
 * Author:  liquan@mozihealthcare.cn
 * Date:    2025-10-9
 * Update:
 **********************************************************************/

#ifndef APICLIENT_H
#define APICLIENT_H

#include "common/xlist.hpp"
#include "api/export.h"

/**
 * 接口调用结果状态枚举
 */
enum class CXI_API_EXPORT ApiResultFlag
{
	//排除的信息
	Exclude = -200,
	//未登录
	Unlogin = -100,
	//发生异常
	Exception = -99,
	//Token不一致（在别处登录过）
	TokenNotMatch = -3,
	//Token超时失效
	TokenError = -2,
	//失败
	ServiceError = -1,
	//成功
	Success = 0,
	//参数错误
	ParameterError = 40001,
	//数据格式错误
	DataFormatError = 40002,
	//业务逻辑错误
	ServiceLogicError = 40003,
	//数据已经被修改，需要刷新最新数据
	DataRefreshError = 40004,
	//第三方接口，响应状态码异常
	ExternalResponseStatusException = 40005,
	//第三方接口，异常状态
	ExternalAbnormalStatusError = 40006,
	//第三方接口，正常状态
	ExternalNormalStateError = 40007,
	//数据不存在
	DataNotFound = 40008,
	//业务查询数据大小超过系统限制错误
	ServiceQueryDataLimitError = 40009,
	//验证密码过期
	LoginPwdOutdate = 70001
};

/**
 * 后端接口返回到业务的数据结果结构
 * @tparam T 结果中包含的数据
 */
template<typename T>
struct CXI_API_EXPORT ApiResult
{
private:
	ApiResult();
	void setFlag(ApiResultFlag flag);
	void setMessage(std::string message);
	void setValue(T value);

public:
	/**
	 * 获取结果标识
	 * @return 结果标识
	 */
	ApiResultFlag flag() const;
	/**
	 * 获取结果描述，一般为错误信息
	 * @return 结果描述，一般为错误信息
	 */
	std::string message() const;
	/**
	 * 获取接口返回的数据实体
	 * @return 接口返回的数据实体
	 */
	T value() const;

private:
	ApiResultFlag m_flag;
	std::string m_message;
	T m_value;
};

/**
 * 排序信息类
 */
class CXI_API_EXPORT ApiSort
{
public:
	/**
	 * 排序方向枚举
	 */
	enum SortDirection
	{
		/**
		 * 顺序
		 */
		ASC,
		/**
		 * 倒序
		 */
		DESC
	};

	/**
	 * 实例化排序对象
	 * @param property 排序字段名（对应实体属性名）
	 * @param direction 排序方向
	 */
	ApiSort(std::string property, SortDirection direction);
	/**
	 * 获取排序字段名（对应实体属性名）
	 * @return 排序字段名（对应实体属性名）
	 */
	std::string property() const;
	/**
	 * 获取排序方向
	 * @return 排序方向
	 */
	SortDirection direction() const;

private:
	std::string m_property;
	SortDirection m_direction;
};

/**
 * 查询条件实体结构
 */
struct CXI_API_EXPORT ApiQueryCriteria
{
	/**
	 * 查询值类型枚举
	 */
	enum QueryType
	{
		/**
		 * 字符类型
		 */
		STRING,
		/**
		 * 数字类型
		 */
		NUMBER,
		/**
		 * 日期类型
		 */
		DATE
	};

	/**
	 * 查询条件枚举 = !=等
	 */
	enum QueryCondition
	{
		/**
		 * 等于
		 */
		Equal,
		/**
		 * 不等于
		 */
		NotEqual,
		/**
		 * 大于
		 */
		Greater,
		/**
		 * 大于等于
		 */
		Greater_Equal,
		/**
		 * 小于
		 */
		Less,
		/**
		 * 小于等于
		 */
		Less_Equal,
		/**
		 * 左右LIKE
		 */
		Like_LR,
		/**
		 * 左LIKE
		 */
		Like_L,
		/**
		 * 右LIKE
		 */
		Like_R
	};

	/**
	 * 查询关系枚举
	 */
	enum QueryRelation
	{
		/**
		 * 与关系
		 */
		AND,
		/**
		 * 或关系
		 */
		OR
	};

	ApiQueryCriteria();
	/**
	 * 获取查询字段名
	 * @return 查询字段名
	 */
	std::string property() const;
	/**
	 * 设置查询字段名
	 * @param property 查询字段名
	 */
	void setProperty(std::string property);
	/**
	 * 获取查询关系
	 * @return 查询关系
	 */
	QueryRelation relation() const;
	/**
	 * 设置查询关系
	 * @param relation 查询关系
	 */
	void setRelation(QueryRelation relation);
	/**
	 * 获取查询条件
	 * @return 查询条件
	 */
	QueryCondition condition() const;
	/**
	 * 设置查询条件
	 * @param condition 查询条件
	 */
	void setCondition(QueryCondition condition);
	/**
	 * 获取查询值的类型
	 * @return 查询值的类型
	 */
	QueryType valueType() const;
	/**
	 * 设置查询值的类型
	 * @param valueType 查询值的类型
	 */
	void setValueType(QueryType valueType);
	/**
	 * 获取查询的值
	 * @return 查询的值
	 */
	QVariant value() const;
	/**
	 * 设置查询的值
	 * @param value 查询的值
	 */
	void setValue(QVariant value);
	/**
	 * 获取嵌套查询条件
	 * @return 嵌套查询条件
	 */
	xlist::XList<ApiQueryCriteria> children() const;
	/**
	 * 设置嵌套查询条件
	 * @param children 嵌套查询条件
	 */
	void setChildren(xlist::XList<ApiQueryCriteria> children);

private:
	std::string m_property;                   //查询字段名（对应实体属性名）
	QueryRelation m_relation;                 //查询关系 AND OR
	QueryCondition m_condition;               //查询条件 LIKE IN = !=
	QueryType m_valueType;                    //查询值的类型
	QVariant m_value;                         //查询的值
	xlist::XList<ApiQueryCriteria> m_children;//嵌套查询条件，主要用于IN查询
};

/**
 * 分页实体结构：分页查询及结果返回格式，包含参数信息、排序信息和结果信息。
 */
template <typename PARA, typename RESULT>
struct CXI_API_EXPORT ApiPage
{
	ApiPage();
	/**
	 * 获取当前页号（从1开始）
	 * @return 当前页号（从1开始）
	 */
	int pageNo() const;
	/**
	 * 设置当前页号（从1开始）
	 * @param pageNo 当前页号（从1开始）
	 */
	void setPageNo(int pageNo);
	/**
	 * 获取每页记录数
	 * @return 每页记录数
	 */
	int pageSize() const;
	/**
	 * 设置每页记录数
	 * @param pageSize 每页记录数
	 */
	void setPageSize(int pageSize);
	/**
	 * 获取排序信息集合
	 * @return 排序信息集合
	 */
	xlist::XList<ApiSort> sortList() const;
	/**
	 * 获取查询条件实体集合
	 * @return 查询条件实体集合
	 */
	xlist::XList<ApiQueryCriteria> criteriaList() const;
	/**
	 * 设置查询条件实体集合
	 * @param criteriaList 查询条件实体集合
	 */
	void setCriteriaList(xlist::XList<ApiQueryCriteria> criteriaList);
	/**
	 * 获取参数对象
	 * @return 参数对象
	 */
	PARA parameter() const;
	/**
	 * 设置参数对象
	 * @param parameter 参数对象
	 */
	void setParameter(PARA parameter);
	/**
	 * 获取数据总条数
	 * @return 数据总条数
	 */
	int iTotalRecords() const;
	/**
	 * 获取总页数
	 * @return 总页数
	 */
	int totalPages() const;
	/**
	 * 获取下一页页码
	 * @return 下一页页码
	 */
	int nextPage() const;
	/**
	 * 获取上一页页码
	 * @return 上一页页码
	 */
	int prePage() const;
	/**
	 * 获取是否有下一页
	 * @return 是否有下一页
	 */
	bool hasNext() const;
	/**
	 * 获取是否有上一页
	 * @return 是否有上一页
	 */
	bool hasPre() const;
	/**
	 * 获取开始记录序号
	 * @return 开始记录序号
	 */
	int first() const;
	/**
	 * 获取最后记录序号
	 * @return 最后记录序号
	 */
	int last() const;
	/**
	 * 获取查询结果集
	 * @return 查询结果集
	 */
	xlist::XList<RESULT> result() const;

private:
	/**
	 * 设置排序信息集合
	 * @param sortList 排序信息集合
	 */
	void setSortList(xlist::XList<ApiSort> sortList);
	/**
	 * 设置数据总条数
	 * @param iTotalRecords 数据总条数
	 */
	void setTotalRecords(int iTotalRecords);
	/**
	 * 设置总页数
	 * @param totalPages 总页数
	 */
	void setTotalPages(int totalPages);
	/**
	 * 设置下一页页码
	 * @param nextPage 下一页页码
	 */
	void setNextPage(int nextPage);
	/**
	 * 设置上一页页码
	 * @param prePage 上一页页码
	 */
	void setPrePage(int prePage);
	/**
	 * 设置是否有下一页
	 * @param hasNext 是否有下一页
	 */
	void setHasNext(bool hasNext);
	/**
	 * 设置是否有上一页
	 * @param hasPre 是否有上一页
	 */
	void setHasPre(bool hasPre);
	/**
	 * 设置开始记录序号
	 * @param first 开始记录序号
	 */
	void setFirst(int first);
	/**
	 * 设置最后记录序号
	 * @param last 最后记录序号
	 */
	void setLast(int last);
	/**
	 * 设置查询结果集
	 * @param result 查询结果集
	 */
	void setResult(xlist::XList<RESULT> result);

	int m_pageNo;//当前页号（从1开始）
	int m_pageSize;//每页记录数
	xlist::XList<ApiSort> m_sortList;//排序信息集合
	xlist::XList<ApiQueryCriteria> m_criteriaList;//查询条件实体集合
	PARA m_parameter;//参数对象
	int m_iTotalRecords;//数据总条数
	int m_totalPages;//总页数
	int m_nextPage;//下一页页码
	int m_prePage;//上一页页码
	bool m_hasNext;//是否有下一页
	bool m_hasPre;//是否有上一页
	int m_first;//开始记录序号
	int m_last;//最后记录序号
	xlist::XList<RESULT> m_result;//查询结果集
};

/**
 * 通用的供客户端上层调用后端接口的工具类
 */
class CXI_API_EXPORT ApiClient {
public:
	static void test();
	/**
	 * 获取服务器当前时间
	 * @return 服务器当前时间
	 */
	static QDateTime systemDateTime();
	/**
	 * 按账号获取用户姓名
	 * @param usrLogin 用户账号
	 * @return 用户姓名
	 */
	static ApiResult<std::string> getUserName(const std::string& usrLogin);
	/**
	 * 获取用户登录状态
	 * @param usrLogin 用户名作为登录字段，若不是则为空
	 * @param usrJobno 工号作为登录字段，若不是则为空
	 * @param usrPwd 密码
	 * @return true是已登录，false是未登录
	 */
	static ApiResult<bool> getLoginStat(const std::string& usrLogin, const std::string& usrJobno, const std::string& usrPwd);
};



#endif //APICLIENT_H
